"""
配置管理模块

提供配置文件的加载、验证和管理功能
"""

import os
from pathlib import Path
from typing import Any, Dict, Optional, Union
from omegaconf import OmegaConf
import yaml


class Config:
    """配置管理器"""
    
    def __init__(self, config_path: Optional[Union[str, Path]] = None):
        """
        初始化配置管理器
        
        Args:
            config_path: 配置文件路径
        """
        self.config = {}
        if config_path is not None:
            self.load_config(config_path)
    
    def load_config(self, config_path: Union[str, Path]) -> None:
        """加载配置文件"""
        config_path = Path(config_path)
        
        if not config_path.exists():
            raise FileNotFoundError(f"配置文件不存在: {config_path}")
        
        if config_path.suffix.lower() in ['.yaml', '.yml']:
            with open(config_path, 'r', encoding='utf-8') as f:
                self.config = yaml.safe_load(f)
        elif config_path.suffix.lower() == '.json':
            import json
            with open(config_path, 'r', encoding='utf-8') as f:
                self.config = json.load(f)
        else:
            raise ValueError(f"不支持的配置文件格式: {config_path.suffix}")
    
    def get(self, key: str, default: Any = None) -> Any:
        """获取配置值"""
        keys = key.split('.')
        value = self.config
        
        for k in keys:
            if isinstance(value, dict) and k in value:
                value = value[k]
            else:
                return default
        
        return value
    
    def set(self, key: str, value: Any) -> None:
        """设置配置值"""
        keys = key.split('.')
        config = self.config
        
        for k in keys[:-1]:
            if k not in config:
                config[k] = {}
            config = config[k]
        
        config[keys[-1]] = value
    
    def update(self, other: Dict[str, Any]) -> None:
        """更新配置"""
        self.config.update(other)
    
    def save_config(self, save_path: Union[str, Path]) -> None:
        """保存配置到文件"""
        save_path = Path(save_path)
        save_path.parent.mkdir(parents=True, exist_ok=True)
        
        if save_path.suffix.lower() in ['.yaml', '.yml']:
            with open(save_path, 'w', encoding='utf-8') as f:
                yaml.dump(self.config, f, default_flow_style=False, allow_unicode=True)
        elif save_path.suffix.lower() == '.json':
            import json
            with open(save_path, 'w', encoding='utf-8') as f:
                json.dump(self.config, f, indent=2, ensure_ascii=False)
        else:
            raise ValueError(f"不支持的配置文件格式: {save_path.suffix}")
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return self.config.copy()
    
    def __getitem__(self, key: str) -> Any:
        """支持字典式访问"""
        return self.get(key)
    
    def __setitem__(self, key: str, value: Any) -> None:
        """支持字典式设置"""
        self.set(key, value)
    
    def __contains__(self, key: str) -> bool:
        """支持in操作符"""
        return self.get(key) is not None


def load_config(config_path: Union[str, Path]) -> Config:
    """加载配置文件"""
    return Config(config_path)


def create_default_config() -> Dict[str, Any]:
    """创建默认配置"""
    return {
        # 数据配置
        "data": {
            "dataset_path": "data/raw/echocardiogram",
            "processed_path": "data/processed/segmentation",
            "batch_size": 4,
            "num_workers": 4,
            "image_size": [512, 512],
            "normalize": True
        },
        
        # 模型配置
        "model": {
            "name": "baseline_sam",
            "backbone": "vit_h",
            "pretrained": True,
            "num_classes": 1,
            "dropout": 0.1
        },
        
        # 训练配置
        "training": {
            "epochs": 100,
            "learning_rate": 1e-4,
            "weight_decay": 1e-4,
            "scheduler": "cosine",
            "warmup_epochs": 10,
            "save_interval": 10,
            "eval_interval": 5
        },
        
        # 推理配置
        "inference": {
            "batch_size": 1,
            "use_tta": False,
            "save_predictions": True,
            "output_dir": "outputs/predictions"
        },
        
        # 实验配置
        "experiment": {
            "name": "baseline_experiment",
            "description": "Baseline SAM experiment",
            "tags": ["baseline", "sam"],
            "save_dir": "experiments/baseline"
        },
        
        # 日志配置
        "logging": {
            "level": "INFO",
            "log_dir": "logs",
            "console_output": True,
            "file_output": True
        },
        
        # 设备配置
        "device": {
            "cuda": True,
            "device_ids": [0],
            "mixed_precision": False
        }
    }


def merge_configs(*configs: Dict[str, Any]) -> Dict[str, Any]:
    """合并多个配置"""
    merged = {}
    for config in configs:
        merged.update(config)
    return merged


def validate_config(config: Dict[str, Any]) -> bool:
    """验证配置的有效性"""
    required_keys = [
        "data.dataset_path",
        "model.name",
        "training.epochs",
        "training.learning_rate"
    ]
    
    for key in required_keys:
        if not _get_nested_value(config, key):
            raise ValueError(f"缺少必需的配置项: {key}")
    
    return True


def _get_nested_value(config: Dict[str, Any], key: str) -> Any:
    """获取嵌套字典的值"""
    keys = key.split('.')
    value = config
    
    for k in keys:
        if isinstance(value, dict) and k in value:
            value = value[k]
        else:
            return None
    
    return value

